<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="../css/main.css" media="all" rel="stylesheet" type="text/css" />
<link href="../css/highlight.css" media="all" rel="stylesheet" type="text/css" />
<link href="../css/print.css" media="print" rel="stylesheet" type="text/css" />
<title>第12章 - キャッシュ</title>
</head>

<body>
<div class="navigation">

<table width="100%">
<tr>
<td width="40%" align="left"><a href="11-Ajax-Integration.html">前の章</a></td>
<td width="20%" align="center"><a href="index.html">ホーム</a></td>
<td width="40%" align="right"><a href="13-I18n-and-L10n.html">次の章</a></td>
</tr>
</table>
<hr/>
</div>

<div>
<a name="chapter.12.caching" id="chapter.12.caching"></a><h1>第12章 - キャッシュ</h1>

<p>アプリケーションを加速する方法の1つは将来のリクエストのために生成されたHTMLコード、もしくは全ページのチャンク(塊)を保存することです。このテクニックはキャッシング(caching)という名前で知られ、サーバーサイドとクライアントサイドで管理できます。</p>

<p>symfonyは柔軟なサーバーキャッシュシステムを提供します。キャッシュによって、YAMLファイルに基づいたとても直感的なセットアップを通して、全レスポンス、アクションの結果、部分テンプレートもしくはテンプレートフラグメントをファイルに保存できるようにします。基本的なデータが変化するとき、コマンドラインもしくは、特別なアクションメソッドによってキャッシュの選択した部分を簡単にクリアできます。symfonyもHTTP 1.1のヘッダーを通してクライアントサイドのキャッシュをコントロールする簡単な方法を提供します。この章ではこれらすべての題目を扱い、キャッシュがアプリケーションにもたらす改善をモニタリングするいくつかのティップスを提示します。</p>

<div class="toc">
<dl>
<dt><a href="#caching.the.response">12.1. レスポンスをキャッシュする</a></dt>
<dd><dl>
<dt><a href="#global.cache.settings">12.1.1. グローバルキャッシュの設定</a></dt>
<dt><a href="#caching.an.action">12.1.2. アクションをキャッシュする</a></dt>
<dt><a href="#caching.a.partial.component.or.component.slot">12.1.3. 部分テンプレート、コンポーネント、もしくはコンポーネントスロットをキャッシュする</a></dt>
<dt><a href="#caching.a.template.fragment">12.1.4. テンプレートのフラグメントをキャッシュする</a></dt>
<dt><a href="#configuring.the.cache.dynamically">12.1.5. キャッシュを動的に設定する</a></dt>
<dt><a href="#using.the.super.fast.cache">12.1.6. スーパーファーストキャッシュを利用する</a></dt>
</dl></dd>
<dt><a href="#removing.items.from.the.cache">12.2. キャッシュから項目を除去する</a></dt>
<dd><dl>
<dt><a href="#clearing.the.entire.cache">12.2.1. キャッシュ全体をクリアする</a></dt>
<dt><a href="#clearing.selective.parts.of.the.cache">12.2.2. 抜粋した部分のキャッシュをクリアする</a></dt>
<dt><a href="#clearing.several.cache.parts.at.once.new.in.symfony.1.1">12.2.3. 一度に複数のキャッシュ部分をクリアする(1.1の新しい機能)</a></dt>
<dt><a href="#clearing.cache.across.applications.new.in.symfony.1.1">12.2.4. 複数のアプリケーションにまたがったキャッシュをクリアする(symfony 1.1の新しい機能)</a></dt>
</dl></dd>
<dt><a href="#testing.and.monitoring.caching">12.3. キャッシュのテストとモニタリング</a></dt>
<dd><dl>
<dt><a href="#building.a.staging.environment">12.3.1. ステージング環境を作成する</a></dt>
<dt><a href="#monitoring.performance">12.3.2. パフォーマンスをモニタリングする</a></dt>
<dt><a href="#benchmarking">12.3.3. ベンチマーキングを行う</a></dt>
<dt><a href="#identifying.cache.parts">12.3.4. キャッシュの一部を識別する</a></dt>
</dl></dd>
<dt><a href="#http.1.1.and.clientside.caching">12.4. HTTP 1.1とクライアントサイドのキャッシュ</a></dt>
<dd><dl>
<dt><a href="#adding.an.etag.header.to.avoid.sending.unchanged.content">12.4.1. 変更されていない内容の送信を回避するためにETagヘッダーを追加する</a></dt>
<dt><a href="#adding.a.lastmodified.header.to.avoid.sending.still.valid.content">12.4.2. まだ有効な内容の送信を回避するためにLast-Modifiedヘッダーを追加する</a></dt>
<dt><a href="#adding.vary.headers.to.allow.several.cached.versions.of.a.page">12.4.3. キャッシュ済みのページを利用可能にするVaryヘッダーを追加する</a></dt>
<dt><a href="#adding.a.cachecontrol.header.to.allow.clientside.caching">12.4.4. クライアントサイドのキャッシュを可能にするCache-Controlヘッダーを追加する</a></dt>
</dl></dd>
<dt><a href="#summary">12.5. まとめ</a></dt>
</dl>
</div>
<a name="caching.the.response" id="caching.the.response"></a><h2>レスポンスをキャッシュする</h2>

<p>HTMLのキャッシュの原則はシンプルです: ユーザーに送信されるHTMLのコードの一部もしくはすべてが似たようなリクエストに対して再利用できます。このHTMLのコードは特別な場所(symfonyの<code>cache/</code>フォルダー)に保存されます。ここでフロントコントローラーはアクションを実行するまえにこのコードを探します。キャッシュされたバーションが見つかる場合、アクションを実行しないでこのコードが送られるので、処理速度が大いに加速します。キャッシュが見つからない場合、アクションが実行され、将来のリクエストのために結果(ビュー)がキャッシュ用のフォルダーに保存されます。</p>

<p>すべてのページが動的な情報を含むので、デフォルトではHTMLのキャッシュは無効です。パフォーマンスを改善するために有効にするかどうかはサイトの管理者次第です。</p>

<p>symfonyは3つの異なるタイプのHTMLキャッシュを扱います:</p>

<ul>
<li>アクションのキャッシュ(レイアウトあり、もしくはなし)</li>
<li>部分テンプレート、コンポーネント、もしくはコンポーネントスロットのキャッシュ</li>
<li>テンプレートフラグメントのキャッシュ</li>
</ul>

<p>最初の2つのタイプはYAMLの設定ファイルで扱われます。テンプレートフラグメントのキャッシュはテンプレートのヘルパー関数の呼び出しによって管理されます。</p>

<a name="global.cache.settings" id="global.cache.settings"></a><h3>グローバルキャッシュの設定</h3>

<p>プロジェクトのそれぞれのアプリケーションのために、<code>settings.yml</code>ファイルのキャッシュ設定において、HTMLキャッシュメカニズムは環境ごとに有効、もしくは無効(デフォルト)にできます。リスト12-1はキャッシュの有効のお手本を示しています。</p>

<p>リスト12-1 - キャッシュを有効にする(<code>frontend/config/settings.yml</code>)</p>

<pre><code>dev:
  .settings:
    cache:                  on
</code></pre>

<a name="caching.an.action" id="caching.an.action"></a><h3>アクションをキャッシュする</h3>

<p>静的な情報(データベースに依存しないもしくはセッションに依存するデータ)を表示するアクション、もしくは修正なしでデータベースから情報を読みとるアクション(典型的なものはGETリクエスト)はしばしばキャッシュのために理想的です。図12-1はこの場合においてページの要素がキャッシュされることを示しています: アクションの結果(そのテンプレート)もしくはレイアウトとのアクションの結果です。</p>

<p>図12-1 - アクションをキャッシュする</p>

<p><img src="images/F1201.png" alt="アクションをキャッシュする" title="アクションをキャッシュする" /></p>

<p>たとえば、Webサイトのすべてのユーザーのリストを返す<code>user/list</code>アクションを考えてください。ユーザーが修正、追加、もしくは除去(そしてこのことが"キャッシュから項目を除去する"のセクションで検討されます)されないかぎり、このリストはつねに同じ情報を示しますので、キャッシュのためのよい候補です。</p>

<p>キャッシュの有効と設定、アクションによるアクションはモジュールの<code>config/</code>ディレクトリに設置された<code>cache.yml</code>ファイルのなかで定義されます。例としてリスト12-2をご覧ください。</p>

<p>リスト12-2 - アクションのためにキャッシュを有効にする(<code>frontend/modules/user/config/cache.yml</code>)</p>

<pre><code>list:
  enabled:     on
  with_layout: false   # デフォルト値
  lifetime:    86400   # デフォルト値
</code></pre>

<p>この設定は、キャッシュが<code>list</code>アクションのためにオンになっていること、およびレイアウトがアクション(デフォルトのふるまい)によってキャッシュされないことを保証します。このことは、キャッシュ済みのアクションが存在する場合でも、(部分テンプレートとコンポーネントと一緒に)レイアウトは再度処理されることを意味します。<code>with_layout</code>設定が`trueに設定された場合は、レイアウトはアクションによってキャッシュされ、再度処理されることはありません。</p>

<p>キャッシュの設定をテストするには、ブラウザーから開発環境のアクションを呼び出します。</p>

<pre><code>http://myapp.example.com/frontend_dev.php/user/list
</code></pre>

<p>ページ内のアクションの領域周辺の境界に注目してください。最初に、領域は青色のヘッダーで、ページがキャッシュから由来するものではないことを示します。ページをリフレッシュすると、アクションの領域が黄色のヘッダーを持ち、キャッシュから由来するものであることを表します(レスポンスの時間単位で目立って加速されます)。後の章でキャッシュのテストとモニタリングを行う方法について詳しく学ぶことになります。</p>

<blockquote class="note"><p>
  スロットはテンプレートの一部で、アクションをキャッシュすることはこのアクションのテンプレートのなかで定義されたスロットの値を保存することにもなります。ですのでキャッシュはスロットに対してネイティブに機能します。</p>
</blockquote>

<p>キャッシュシステムは引数を持つページに対しても機能します。<code>user</code>モジュールが、たとえば、ユーザーの詳細を表示するために<code>id</code>引数を必要とする<code>show</code>アクションを持つとします。リスト12-3で示されるように、このアクションに対してキャッシュを有効にするには<code>cache.yml</code>ファイルを修正します。</p>

<p><code>cache.yml</code>の内容を見やすくするには、リスト12-3でも示されるように、<code>all:</code>キーの下でモジュールのすべてのアクションのための設定を再編成することができます。</p>

<p>リスト12-3 - <code>cache.yml</code>の全内容の例(<code>frontend/modules/user/config/cache.yml</code>)</p>

<pre><code>list:
  enabled:    on
show:
  enabled:    on

all:
  with_layout: false   # デフォルト値
  lifetime:    86400   # デフォルト値
</code></pre>

<p><code>user/show</code>アクションを異なる<code>id</code>引数で呼び出すたびにキャッシュ内で新しいレコードが作られます。ですので、このためのキャッシュ:</p>

<pre><code>http://myapp.example.com/user/show/id/12
</code></pre>

<p>はつぎのキャッシュとは異なります:</p>

<pre><code>http://myapp.example.com/user/show/id/25
</code></pre>

<blockquote class="caution"><p>
  POSTメソッドもしくはGETパラメーターによって呼び出されたアクションはキャッシュされません。</p>
</blockquote>

<p><code>with_layout</code>設定は少し説明が必要です。この設定はどの種類のデータがキャッシュに保存されるのか実際に決定します。レイアウトなしのキャッシュに対しては、テンプレートの実行結果とアクション変数がキャッシュに保存されます。レイアウトありのキャッシュに対しては、レスポンスオブジェクト全体が保存されます。レイアウトありのキャッシュはレイアウトなしのキャッシュよりもずっと速いことを意味します。</p>

<p>機能的に余裕があれば(つまりレイアウトがセッションデータに依存しない場合)、レイアウトありのキャッシュを選ぶべきです。不幸なことに、レイアウトは動的な要素(たとえば、接続したユーザーの名前)を含むことが多いので、レイアウトなしのアクションのキャッシュはもっとも共通した設定です。しかしながら、RSSフィード、ポップアップとCookieに依存しないページはレイアウトありでキャッシュできます。</p>

<a name="caching.a.partial.component.or.component.slot" id="caching.a.partial.component.or.component.slot"></a><h3>部分テンプレート、コンポーネント、もしくはコンポーネントスロットをキャッシュする</h3>

<p>7章では、<code>include_partial()</code>ヘルパーを利用して、いくつかのテンプレートにまたがるコードのフラグメントを再利用する方法を説明しました。部分テンプレートはアクションとしてキャッシュすることが簡単で、図12-2で示されるように、キャッシュの有効方法は同じルールに従います。</p>

<p>図12-2 - 部分テンプレート、コンポーネント、コンポーネントスロットをキャッシュする</p>

<p><img src="images/F1202.png" alt="部分テンプレート、コンポーネント、コンポーネントスロットをキャッシュする" title="部分テンプレート、コンポーネント、コンポーネントスロットをキャッシュする" /></p>

<p>たとえば、リスト12-4は<code>user</code>モジュールに設置された<code>_my_partial.php</code>上でキャッシュを有効にするために<code>cache.yml</code>ファイルを編集する方法を示しています。この場合において<code>with_layout</code>設定は意味を成さないことを覚えておいてください。</p>

<p>リスト12-4- 部分テンプレートのキャッシュ設定(<code>frontend/modukes/user/config/cache.yml</code>)</p>

<pre><code>_my_partial:
  enabled:    on
list:
  enabled:    on
...
</code></pre>

<p>この部分テンプレートを利用するすべてのテンプレートは実際には部分テンプレートのPHPコードを実行しませんが、代わりにキャッシュバーションを使います。</p>

<pre class="php"><span class="kw2">&lt;?php</span> include_partial<span class="br0">&#40;</span><span class="st_h">'user/my_partial'</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span></pre>

<p>アクションに関しては、部分テンプレートの結果がパラメーターに依存するときに部分テンプレートキャッシュも該当します。キャッシュシステムはパラメーターの異なる値と同じ数のバージョンのテンプレートを保存します。</p>

<pre class="php"><span class="kw2">&lt;?php</span> include_partial<span class="br0">&#40;</span><span class="st_h">'user/my_other_partial'</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'foo'</span> <span class="sy0">=&gt;</span> <span class="st_h">'bar'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span></pre>

<blockquote class="tip"><p>
  アクションのキャッシュは部分テンプレートのキャッシュよりもはるかに強力です。アクションがキャッシュされたとき、テンプレートの実行でさえも行われないからです; テンプレートが部分テンプレートの呼び出しを含む場合、これらの呼び出しは実行されません。それゆえ、部分テンプレートのキャッシュは、アクションを呼び出す際もしくはレイアウトに含まれる部分テンプレートに対してアクションのキャッシュを使わない場合のみ便利です。</p>
</blockquote>

<p>7章を少し思い出してみましょう: コンポーネントは部分テンプレートのトップに設置される軽量のアクションで、コンポーネントスロットはアクションを呼び出すことにしたがって変化するアクションのためのコンポーネントです。これら2つのインクルージョンのタイプは部分テンプレートとよく似ており、同じ方法でキャッシュをサポートします。たとえば、現在の日時を表示するために、グローバルレイアウトが<code>include_component('general/day')</code>で<code>day</code>と呼ばれているコンポーネントをインクルードする場合、このコンポーネント上のキャッシュを有効にするには<code>general</code>モジュールの<code>cache.yml</code>ファイルをつぎのように設定します:</p>

<pre><code>_day:
  enabled: on
</code></pre>

<p>コンポーネントもしくは部分テンプレートをキャッシュするとき、呼び出しているすべてのテンプレートに対してキャッシュの単独バージョンか、それぞれのテンプレートに対するバージョンを保存するか決めなければなりません。デフォルトでは、コンポーネントはそれを呼び出すテンプレートに対して独立して保存されます。しかしながら文脈依存のコンポーネント、たとえばそれぞれのアクションで異なるサイドバーを表示するコンポーネント、はテンプレートがそれを呼び出す回数と同じ回数だけ保存されます。つぎのように<code>contextual</code>パラメーターを<code>true</code>に設定することを前提にする場合、キャッシュシステムはこの事例を扱うことができます:</p>

<pre><code>_day:
  contextual: true
  enabled:   on
</code></pre>

<blockquote class="note"><p>
  アプリケーションの<code>cache.yml</code>のなかでキャッシュの設定を宣言することを前提にする場合、グローバルコンポーネント(アプリケーションの<code>templates</code>ディレクトリに設置される)をキャッシュできます。</p>
</blockquote>

<a name="caching.a.template.fragment" id="caching.a.template.fragment"></a><h3>テンプレートのフラグメントをキャッシュする</h3>

<p>アクションのキャッシュはアクションの部分集合のみに適用されます。ほかのアクションに対して、データを更新する、もしくはテンプレートでセッションに依存する情報を表示するアクションなど、は異なる方法ですがまだキャッシュの改善の余地はあります。symfonyは3つのキャッシュタイプを提供します。これらはテンプレートのフラグメント専用でテンプレート内部で直接有効にできます。このモードにおいて、図12-3で示されるように、アクションはつねに実行され、テンプレートは実行されたフラグメントとキャッシュのフラグメントに分割されます。</p>

<p>図12-3 テンプレートのフラグメントをキャッシュする</p>

<p><img src="images/F1203.png" alt="テンプレートのフラグメントをキャッシュする" title="テンプレートのフラグメントをキャッシュする" /></p>

<p>たとえば、最後にアクセスしたユーザーのリンクを表示するユーザーのリストがある場合、この情報は動的です。<code>cache()</code>ヘルパーはキャッシュに保存されたテンプレートの部分を定義します。リスト12-5で構文の詳細をご覧ください。</p>

<p>リスト12-5 - <code>cache()</code>ヘルパーを使う(<code>frontend/modules/user/templates/listSuccess.php</code>)</p>

<pre class="php">&lt;!-- Code executed each time --&gt;
<span class="kw2">&lt;?php</span> <span class="kw1">echo</span> link_to<span class="br0">&#40;</span><span class="st_h">'last accessed user'</span><span class="sy0">,</span> <span class="st_h">'user/show?id='</span><span class="sy0">.</span><span class="re0">$last_accessed_user_id</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span>
&nbsp;
&lt;!-- Cached code --&gt;
<span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>cache<span class="br0">&#40;</span><span class="st_h">'users'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="sy1">?&gt;</span>
  <span class="kw2">&lt;?php</span> <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$users</span> <span class="kw1">as</span> <span class="re0">$user</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="sy1">?&gt;</span>
    <span class="kw2">&lt;?php</span> <span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">getName</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span>
  <span class="kw2">&lt;?php</span> <span class="kw1">endforeach</span><span class="sy0">;</span> <span class="sy1">?&gt;</span>
  <span class="kw2">&lt;?php</span> cache_save<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="sy1">?&gt;</span></pre>

<p>つぎのように動作します:</p>

<ul>
<li>'users'と名づけられたキャッシュ済みのフラグメントが見つかる場合、これは<code>&lt;?php if (!cache($unique_fragment_name)): ?&gt;</code>と<code>&lt;?php endif; ?&gt;</code>の行の間のコードを置き換えるために使われます。</li>
<li>見つからない場合、これらの行の間のコードは処理されキャッシュに保存されます。コードはユニークなフラグメントの名前で識別されます。</li>
</ul>

<p>このような行が含まれないコードはつねに処理され、キャッシュされません。</p>

<blockquote class="caution"><p>
  アクション(この例では<code>list</code>)はキャッシュを有効にしてはなりません。これはテンプレート全体の実行を回避し、フラグメントのキャッシュの宣言を無視するからです。</p>
</blockquote>

<p>テンプレートフラグメントのキャッシュの使用による加速はアクションのキャッシュによるものよりは重要ではありません。アクションはつねに実行され、テンプレートは部分的に処理され、レイアウトはつねにデコレーションのために使われるからです。</p>

<p>追加のフラグメントを同じテンプレートのなかで宣言できます; しかしながら、それらに対して個別にユニークな名前をつけることで、symfonyのキャッシュシステムはこれらをあとで見つけることができます。</p>

<p>アクションとコンポーネントに関しては、キャッシュされたフラグメントは<code>cache()</code>ヘルパーへの呼び出しの2番目の引数として秒単位の期限を持ちます。</p>

<pre class="php"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>cache<span class="br0">&#40;</span><span class="st_h">'users'</span><span class="sy0">,</span> <span class="nu0">43200</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="sy1">?&gt;</span></pre>

<p>パラメーターがヘルパーに渡されない場合、デフォルトのキャッシュの期限(86400秒もしくは1日)が使われます。</p>

<blockquote class="tip"><p>
  アクションをキャッシュできるようにする別の方法はアクションのルーティングパターンに変化する変数を挿入することです。たとえば、ホームページが接続ユーザーの名前を表示する場合、URLがユーザーのニックネームを含まないかぎり、キャッシュできません。ほかの例は国際化アプリケーションに関するものです: いくつかの翻訳を持つページの上でキャッシュを有効にしたい場合、言語コードを何とかしてURLパターンに含めなければなりません。このトリックはキャッシュにおけるページ数を増やしますが、インタラクティブなアプリケーションを大きく加速するために大いに役立ちます。</p>
</blockquote>

<a name="configuring.the.cache.dynamically" id="configuring.the.cache.dynamically"></a><h3>キャッシュを動的に設定する</h3>

<p><code>cache.yml</code>ファイルはキャッシュの設定を定義する1つの方法ですが、不変であるが故に不便です。しかしながら、symfonyにおいていつものとおり、YAMLよりも無地のPHPを利用できるので、キャッシュを動的に設定できます。</p>

<p>キャッシュの設定を動的に変更したいのはなぜでしょうか？よい例は認証ユーザーと匿名ユーザーのページの内容は異なるが、URLは同じであるページです。記事に対して評価システムを持つ<code>article/show</code>ページを想像してください。評価機能は匿名ユーザーに対して無効です。これらのユーザーに対しては、リンクはログインフォームの表示を行います。このバージョンのページはキャッシュできます。一方で、認証ユーザーに対しては、評価リンクをクリックすることでPOSTリクエストと新しい評価が作成されます。今回、symfonyが動的にページをビルドするにはページに対してキャッシュを無効にしなければなりません。</p>

<p>動的なキャッシュの設定を定義する正しい場所は<code>sfCacheFilter</code>のまえに実行されるフィルターです。本当に、セキュリティ機能と同じように、キャッシュはsymfonyのフィルターです。ユーザーが認証されていない場合だけ<code>article/show</code>ページに対してキャッシュを有効にするには、リスト12-6で示されるように、<code>conditionalCacheFilter</code>をアプリケーションの<code>lib/</code>ディレクトリのなかに作成します。</p>

<p>リスト12-6 - PHPを使ってキャッシュを設定する(<code>frontend/lib/conditinalCacheFilter.class.php</code>)</p>

<pre class="php"><span class="kw2">class</span> conditionalCacheFilter <span class="kw2">extends</span> sfFilter
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> execute<span class="br0">&#40;</span><span class="re0">$filterChain</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$context</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getContext</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re0">$context</span><span class="sy0">-&gt;</span><span class="me1">getUser</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">isAuthenticated</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getParameter</span><span class="br0">&#40;</span><span class="st_h">'pages'</span><span class="br0">&#41;</span> <span class="kw1">as</span> <span class="re0">$page</span><span class="br0">&#41;</span>
      <span class="br0">&#123;</span>
        <span class="re0">$context</span><span class="sy0">-&gt;</span><span class="me1">getViewCacheManager</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addCache</span><span class="br0">&#40;</span><span class="re0">$page</span><span class="br0">&#91;</span><span class="st_h">'module'</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="re0">$page</span><span class="br0">&#91;</span><span class="st_h">'action'</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'lifeTime'</span> <span class="sy0">=&gt;</span> <span class="nu0">86400</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="co1">// つぎのフィルターを実行する</span>
    <span class="re0">$filterChain</span><span class="sy0">-&gt;</span><span class="me1">execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>リスト12-7で示されるように、<code>sfCacheFilter</code>のまえにこのフィルターを<code>filters.yml</code>ファイルに登録しなければなりません。</p>

<p>リスト12-7 - カスタムフィルターを登録する(<code>frontend/config/filters.yml</code>)</p>

<pre><code>...
security: ~

conditionalCache:
  class: conditionalCacheFilter
  param:
    pages:
      - { module: article, action: show }

cache: ~
...
</code></pre>

<p>キャッシュをクリアすれば(新しいフィルタークラスをオートロードするため)、条件つきのキャッシュの準備ができます。これは、認証されていないユーザーに対してだけ、ページパラメーターで定義されたページのキャッシュを有効にします。</p>

<p><code>sfViewCacheManager</code>オブジェクトの<code>addCache()</code>メソッドはモジュールの名前、アクションの名前、そして<code>cache.yml</code>ファイルのなかで定義するパラメーターと同じ内容を持つ連想配列を必要とします。たとえば、<code>article/show</code>をレイアウトありで3600秒の期限の条件でキャッシュしなければならないことを定義したい場合、つぎのように書きます:</p>

<pre class="php"><span class="re0">$context</span><span class="sy0">-&gt;</span><span class="me1">getViewCacheManager</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addCache</span><span class="br0">&#40;</span><span class="st_h">'article'</span><span class="sy0">,</span> <span class="st_h">'show'</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span>
  <span class="st_h">'withLayout'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
  <span class="st_h">'lifeTime'</span>   <span class="sy0">=&gt;</span> <span class="nu0">3600</span><span class="sy0">,</span>
<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<blockquote class="sidebar"><p class="title">
  <strong>代替のキャッシュストレージ</strong></p>
  
  <p>デフォルトでは、symfonyのキャッシュシステムはWebサーバーのハードディスク上のファイルにデータを保存します。メモリ(たとえば<a href="http://www.danga.com/memcached/">memcached</a>経由)もしくはデータベース(いくつかのサーバー間でキャッシュを共有したいもしくはキャッシュの除去を加速したい場合)にキャッシュを保存したい場合を考えます。このためには、symfonyのデフォルトのキャッシュストレージシステムを簡単に変更できます。symfonyのビューキャッシュマネージャーによって使われるキャッシュクラスは<code>factories.yml</code>に定義されるからです。</p>
  
  <p>デフォルトのビューキャッシュストレージファクトリは<code>sfFileCache</code>クラスです:</p>

<pre><code>view_cache:
    class: sfFileCache
    param:
      automaticCleaningFactor: 0
      cacheDir:                %SF_TEMPLATE_CACHE_DIR%
</code></pre>
  
  <p><code>class</code>を独自のキャッシュストレージクラスもしくはsymfonyの代替クラスの1つ(<code>sfAPCCache</code>、<code>sfEAcceleratorCache</code>、<code>sfMemcacheCache</code>、 <code>sfSQLiteCache</code>、と<code>sfXCacheCache</code>を含む)に置き換えることができます。<code>param</code>キーの下で定義されたパラメーターはあなたのクラスの<code>initialize()</code>メソッドに連想配列として渡されます。どのビューキャッシュストレージクラスも<code>sfCache</code>抽象クラスのなかのメソッドをすべて実装しなければなりません。この主題に関する詳しい情報は19章を参照してください。</p>
</blockquote>

<a name="using.the.super.fast.cache" id="using.the.super.fast.cache"></a><h3>スーパーファーストキャッシュを利用する</h3>

<p>キャッシュされたページでさえいくつかのPHPコードの実行をともないます。このようなページのために、symfonyは設定をロードし、レスポンスをビルドするなどの動作を行います。しばらくの間ページが変更されないことが本当にわかっている場合、HTMLコードの結果を直接<code>web/</code>フォルダーに設置することでsymfonyを完全に回避できます。ルーティングルールがサフィックスで終わらない、もしくは<code>.html</code>で終わるパターンを指定するという条件の下で、Apacheの<code>mod_rewrite</code>設定のおかげでこれは機能します。</p>

<p>シンプルなコマンドラインの呼び出しによって、ページ単位で、これを手作業で行うことができます:</p>

<pre><code>&gt; curl http://myapp.example.com/user/list.html &gt; web/user/list.html
</code></pre>

<p>そのあとで、<code>user/list</code>アクションがリクエストされるたびに、Apacheは対応する<code>list.html</code>ページを見つけsymfonyを完全に回避します。トレードオフはもはやsymfonyでページキャッシュをコントロールできないことですが(期限、自動削除など)、速度のゲインは目覚ましいです。</p>

<p>代わりの方法として、<code>sfSuperCache</code>プラグインを利用できます。このプラグインはこの処理を自動化して、期限とキャッシュのクリアをサポートします。プラグインに関して詳しい情報は17章を参照してください。</p>

<blockquote class="sidebar"><p class="title">
  <strong>ほかのスピードアップ戦術</strong></p>
  
  <p>HTMLのキャッシュに加えて、symfonyは他に2つのキャッシュメカニズムを持ちます。これらは完全に自動化され、開発者に対して透過的なものになります。運用環境において、設定とテンプレートの翻訳は介入なしで<code>myproject/cache/config/</code>と<code>myproject/cache/i18n/</code>ディレクトリに保存されたファイルにキャッシュされます。</p>
  
  <p>PHPアクセレータ(eAccelerator、APC、XCacheなど)はオペレーションコードキャッシュモジュールとも呼ばれ、コンパイルされた状態のPHPスクリプトをキャッシュすることでパフォーマンスを増大させるので、コードの解析とコンパイルのオーバーヘッドは徹底的に削減されます。これは大量のコードを含むPropelのクラスに対してとりわけ効果的です。これらのアクセレータはsymfonyと互換性があり、簡単にアプリケーションの速度を3倍にします。これらは大規模な利用者を持つsymfonyアプリケーションに対して運用環境で推奨されます。</p>
  
  <p><code>sfProcessCache</code>クラスによる、それぞれのリクエストに対して同じ処理を行うことを避けるために、PHPアクセレータで、永続的なデータを手動でメモリに保存できます。そしてCPUに負荷のかかる作業の結果をキャッシュしたい場合、おそらく<code>sfFunctionCache</code>オブジェクトを使うことになります。これらのメカニズムに関して詳しい情報については18章を参照してください。</p>
</blockquote>

<a name="removing.items.from.the.cache" id="removing.items.from.the.cache"></a><h2>キャッシュから項目を除去する</h2>

<p>アプリケーションのスクリプトもしくはデータが変化する場合、キャッシュは期限切れの情報を含みます。矛盾とバグを避けるために、あなたのニーズに合わせて、多くの異なる方法でキャッシュの部分を削除できます。</p>

<a name="clearing.the.entire.cache" id="clearing.the.entire.cache"></a><h3>キャッシュ全体をクリアする</h3>

<p>symfonyのコマンドラインの<code>cache:clear</code>タスクはキャッシュ(HTML、設定、ルーティングと国際化のキャッシュ)を削除します。リスト12-8で示されるように、キャッシュの部分集合だけを削除するためにこれを引数に渡すことができます。symfonyのプロジェクトのrootからのみ呼び出すことを覚えておいてください。</p>

<p>リスト12-8 - キャッシュをクリアする</p>

<pre><code>// キャッシュ全体を消去する
&gt; php symfony cache:clear

// 短い構文
&gt; php symfony cc

// frontendアプリケーションのキャッシュのみを削除する
&gt; php symfony cache:clear --app=frontend

// myappアプリケーションのHTMLキャッシュだけを削除する
&gt; php symfony cache:clear --app=frontend --type=template

// frontendアプリケーションの設定のキャッシュのみを削除する
// 組み込みのタイプはconfig、i18n、routing、とtemplate。
&gt; php symfony cache:clear --app=frontend --type=config

// frontendアプリケーションとprod環境のコンフィギュレーションキャッシュのみを削除する
&gt; php symfony cache:clear --app=frontend --type=config --env=prod
</code></pre>

<blockquote class="note"><p>
  Microsoft Windowsのもとでは、二重引用符でオプションを囲まなければならないことがあります:</p>

<pre><code>&gt; php symfony cache:clear "--app=frontend"
</code></pre>
</blockquote>

<a name="clearing.selective.parts.of.the.cache" id="clearing.selective.parts.of.the.cache"></a><h3>抜粋した部分のキャッシュをクリアする</h3>

<p>データベースが更新されたとき、修正されたデータに関連するアクションのキャッシュをクリアしなければなりません。キャッシュ全体をクリアできましたが、モデルの変更に関係のない既存のすべてのキャッシュされたアクションに対しては無駄な作業です。これが<code>sfViewCacheManager</code>オブジェクトの<code>remove()</code>メソッドを適用する事例です。これは引数として内部URIを必要とし(<code>link_to()</code>に提供する引数と同じ種類のもの)、関連するアクションのキャッシュを削除します。</p>

<p>たとえば、<code>user</code>モジュールの<code>update</code>アクションが<code>User</code>オブジェクトのカラムを修正することを想像してください。キャッシュ済みの<code>list</code>アクションと<code>show</code>アクションをクリアすることが必要です。さもなければエラーのあるデータを含む古いバージョンが表示されます。これを処理するには、リスト12-9で示されるように、<code>remove()</code>メソッドを使います。</p>

<p>リスト12-9 - 任意のアクションに対してキャッシュをクリアする(<code>modules/user/actions/actions.class.php</code>)</p>

<pre class="php"><span class="kw2">public</span> <span class="kw2">function</span> executeUpdate<span class="br0">&#40;</span><span class="re0">$request</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
  <span class="co1">// ユーザーを更新する</span>
  <span class="re0">$user_id</span> <span class="sy0">=</span> <span class="re0">$request</span><span class="sy0">-&gt;</span><span class="me1">getParameter</span><span class="br0">&#40;</span><span class="st_h">'id'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="re0">$user</span> <span class="sy0">=</span> UserPeer<span class="sy0">::</span><span class="me2">retrieveByPk</span><span class="br0">&#40;</span><span class="re0">$user_id</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">foward404Unless</span><span class="br0">&#40;</span><span class="re0">$user</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">setName</span><span class="br0">&#40;</span><span class="re0">$request</span><span class="sy0">-&gt;</span><span class="me1">getParameter</span><span class="br0">&#40;</span><span class="st_h">'name'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="sy0">...</span>
  <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">save</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// このユーザーに関連するアクションに対するキャッシュをクリアする</span>
  <span class="re0">$cacheManager</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getContext</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getViewCacheManager</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/list'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?id='</span><span class="sy0">.</span><span class="re0">$user_id</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="sy0">...</span>
<span class="br0">&#125;</span></pre>

<p>キャッシュされた部分テンプレート、コンポーネント、コンポーネントスロットを除去する作業は少々複雑です。任意のタイプのパラメーター(オブジェクトを含む)をこれらに渡すことができるので、あとでキャッシュバージョンを識別することが不可能だからです。部分テンプレートに焦点を当てて説明します。このしくみはほかのテンプレートのコンポーネントについても同様です。symfonyはキャッシュされた部分テンプレートを、特別なプレフィックス(<code>sf_cache_partial</code>)、モジュールの名前、部分テンプレートの名前、に加えて呼び出すために使われるすべてのパラメーターのハッシュで識別します:</p>

<pre class="php">// 呼び出された部分テンプレート
<span class="kw2">&lt;?php</span> include_partial<span class="br0">&#40;</span><span class="st_h">'user/my_partial'</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'user'</span> <span class="sy0">=&gt;</span> <span class="re0">$user</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span>
&nbsp;
// はつぎのようなキャッシュに分類される
@sf_cache_partial?module=user&amp;action=_my_partial&amp;sf_cache_key=bf41dd9c84d59f3574a5da244626dcc8</pre>

<p>理論上では、識別するために使われるパラメーターのハッシュの値を知っているのであれば、キャッシュされた部分テンプレートを<code>remove()</code>メソッドで削除できます。しかし、これは現実的な方法ではありません。幸いにして、<code>sf_cache_key</code>パラメーターを<code>include_partial()</code>ヘルパー呼び出しに追加する場合、あなたにとって既知のものとしてキャッシュのなかの部分テンプレートを識別できます。リスト12-10で見ることができるように、単独のキャッシュされた部分テンプレートをクリアする作業、たとえば、修正された<code>User</code>に基づいた部分テンプレートからキャッシュをクリーンアップする作業が簡単になります。</p>

<p>リスト12-10 - 部分テンプレートをキャッシュからクリアする</p>

<pre class="php"><span class="kw2">&lt;?php</span> include_partial<span class="br0">&#40;</span><span class="st_h">'user/my_partial'</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span>
  <span class="st_h">'user'</span>         <span class="sy0">=&gt;</span> <span class="re0">$user</span><span class="sy0">,</span>
  <span class="st_h">'sf_cache_key'</span> <span class="sy0">=&gt;</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#41;</span> <span class="sy1">?&gt;</span>
&nbsp;
//つぎのようにキャッシュに分類される
@sf_cache_partial?module=user&amp;action=_my_partial&amp;sf_cache_key=12
&nbsp;
// つぎのコードでキャッシュの特定のユーザーに対する_my_partialをクリアする
$cacheManager-&gt;remove('@sf_cache_partial?module=user&amp;action=_my_partial&amp;sf_cache_key='.$user-&gt;getId());</pre>

<p>テンプレートフラグメントをクリアするには、同じ<code>remove()</code>メソッドを使います。キャッシュのフラグメントを指定するキーは同じ<code>sf_cache_partial</code>のプレフィックス、モジュールの名前、アクションの名前と<code>sf_cache_key/</code>で構成されます(キャッシュフラグメントのユニークな名前は<code>cache()</code>ヘルパーに含まれます)。リスト12-11は例を示しています。</p>

<p>リスト12-11 - キャッシュから由来するテンプレートフラグメントをクリアする</p>

<pre class="php">&lt;!-- Cached code --&gt;
<span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>cache<span class="br0">&#40;</span><span class="st_h">'users'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">:</span> <span class="sy1">?&gt;</span>
  ... // Whatever
  <span class="kw2">&lt;?php</span> cache_save<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="sy1">?&gt;</span>
<span class="kw2">&lt;?php</span> <span class="kw1">endif</span><span class="sy0">;</span> <span class="sy1">?&gt;</span>
&nbsp;
// つぎのようにキャッシュに分類される
@sf_cache_partial?module=user&amp;action=list&amp;sf_cache_key=users
&nbsp;
// つぎのコードでクリアする
$cacheManager-&gt;remove('@sf_cache_partial?module=user&amp;action=list&amp;sf_cache_key=users');</pre>

<blockquote class="sidebar"><p class="title">
  <strong>クリアするキャッシュの選択に悩む</strong></p>
  
  <p><code>cache-clearing</code>ジョブのもっとも扱いにくい部分はデータの更新によってどのアクションが影響されるのかを決定することです。</p>
  
  <p>たとえば、現在のアプリケーションが<code>publication</code>モジュールを持つことを想像してください。そこでは著者の詳細情報(<code>User</code>クラスのインスタンス)と一緒に、公開情報の一覧が表示され(<code>list</code>アクション)説明されます(<code>show</code>アクション)。1つの<code>User</code>レコードの修正はユーザーの公開情報の説明と公開情報の一覧に影響を与えます。このことは、つぎのように、<code>user</code>モジュールの<code>update</code>アクションを追加する必要があることを意味します:</p>

<pre class="php"><span class="re0">$c</span> <span class="sy0">=</span> <span class="kw2">new</span> Criteria<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$c</span><span class="sy0">-&gt;</span><span class="me1">add</span><span class="br0">&#40;</span>PublicationPeer<span class="sy0">::</span><span class="me2">AUTHOR_ID</span><span class="sy0">,</span> <span class="re0">$request</span><span class="sy0">-&gt;</span><span class="me1">getParameter</span><span class="br0">&#40;</span><span class="st_h">'id'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$publications</span> <span class="sy0">=</span> PublicationPeer<span class="sy0">::</span><span class="me2">doSelect</span><span class="br0">&#40;</span><span class="re0">$c</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$cacheManager</span> <span class="sy0">=</span> sfContext<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getViewCacheManager</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$publications</span> <span class="kw1">as</span> <span class="re0">$publication</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
  <span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'publication/show?id='</span><span class="sy0">.</span><span class="re0">$publication</span><span class="sy0">-&gt;</span><span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'publication/list'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>
  
  <p>HTMLのキャッシュを使い始めるとき、誤解されたリレーションが原因で新しいエラーが表示されないように、モデルとアクションの依存関係の展望をクリアに保つ必要があります。HTMLのキャッシュがアプリケーションのどこかで使われる場合、モデルを修正するすべてのアクションはおそらく<code>remove()</code>メソッドの一連の呼び出しを含むべきであることを覚えておいてください。</p>
  
  <p>そして、難しすぎる解析に悩みたくないのであれば、データベースを更新するたびにキャッシュ全体をつねにクリアできます・・・</p>
</blockquote>

<a name="clearing.several.cache.parts.at.once.new.in.symfony.1.1" id="clearing.several.cache.parts.at.once.new.in.symfony.1.1"></a><h3>一度に複数のキャッシュ部分をクリアする(1.1の新しい機能)</h3>

<p><code>remove()</code>メソッドはワイルドカードを持つキーを受けとります。これによって単独の呼び出しでいくつかのキャッシュを削除できるようになります。たとえばつぎのように行うことができます:</p>

<pre class="php"><span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=*'</span><span class="br0">&#41;</span><span class="sy0">;</span>    <span class="co1">// 現在のホストのすべてのユーザーのレコードのキャッシュを削除する</span></pre>

<p>別のよい例は、すべてのURLに言語コードが現れる、複数の言語を扱うアプリケーションです。ユーザーのプロファイルのページへのURLはつぎのようになります:</p>

<pre><code>http://www.myapp.com/en/user/show/id/12
</code></pre>

<p><code>id</code>が<code>12</code>であるユーザーのプロファイルのキャッシュを削除するには、つぎのように簡単に呼び出すことができます:</p>

<pre class="php"><span class="re0">$cache</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?sf_culture=*&amp;id=12'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>これは部分テンプレートに対しても機能します:</p>

<pre class="php"><span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'@sf_cache_partial?module=user&amp;action=_my_partial&amp;sf_cache_key=*'</span><span class="br0">&#41;</span><span class="sy0">;</span>    <span class="co1">// すべてのキーに対して除去する</span></pre>

<p><code>remove()</code>メソッドは2つの追加パラメーターを受けとり、キャッシュをクリアしたいホストとvaryヘッダーを定義できるようにします。symfonyはそれぞれのホストとvaryヘッダーに対して1つのキャッシュバージョンを保存するので、同じコードベースを共有するが同じホスト名を共有しない2つのアプリケーションは異なるキャッシュを使います。これはアプリケーションがサブドメイン(たとえば<code>http://php.askeet.com</code>と<code>http://life.askeet.com</code>)をリクエストパラメーターとして解釈するとき、とても便利です。最後の2つのパラメーターを設定しない場合、symfonyは現在のホストと<code>all</code>のvaryヘッダーに対してキャッシュを除去します。代わりに、別のホストに対してキャッシュを除去したい場合、つぎのように<code>remove()</code>を呼び出します:</p>

<pre class="php"><span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=*'</span><span class="br0">&#41;</span><span class="sy0">;</span>                     <span class="co1">//現在のホストのすべてのユーザーのキャッシュレコードを削除する</span>
<span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=*'</span><span class="sy0">,</span> <span class="st_h">'life.askeet.com'</span><span class="br0">&#41;</span><span class="sy0">;</span>  <span class="co1">// life.askeet.comのホストのすべてのユーザーのキャッシュレコードを削除する</span>
<span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=*'</span><span class="sy0">,</span> <span class="st_h">'*'</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//すべてのホストのすべてのユーザーのキャッシュレコードを削除する</span></pre>

<p><code>remove()</code>メソッドは<code>factories.yml</code>で定義できるすべてのキャッシュストレージで機能します(<code>sfFileCache</code>だけでなく、<code>sfAPCCache</code>、 <code>sfEAcceleratorCache</code>、<code>sfMemcacheCache</code>、<code>sfSQLiteCache</code>、 と<code>sfXCacheCache</code>も).</p>

<a name="clearing.cache.across.applications.new.in.symfony.1.1" id="clearing.cache.across.applications.new.in.symfony.1.1"></a><h3>複数のアプリケーションにまたがったキャッシュをクリアする(symfony 1.1の新しい機能)</h3>

<p>複数のアプリケーションにまたがるキャッシュをクリアすることが問題になる可能性があります。たとえば、管理者が<code>backend</code>アプリケーションの<code>user</code>テーブルのレコードを修正する場合、<code>frontend</code>アプリケーションのこのユーザーに関係するすべてのアクションはキャッシュからクリアされる必要があります。しかし <code>backend</code>アプリケーションが利用できるビューキャッシュマネージャは<code>frontend</code>アプリケーションのルーティングルールがわかりません(アプリケーションはそれぞれ独立しています)。ですのでbackendアプリケーションのなかで以下のコードを書くことはできません:</p>

<pre class="php"><span class="re0">$cacheManager</span> <span class="sy0">=</span> sfContext<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getViewCacheManager</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// backendアプリケーションのビューキャッシュマネージャを読みとる</span>
<span class="re0">$cacheManager</span><span class="sy0">-&gt;</span><span class="me1">remove</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=12'</span><span class="br0">&#41;</span><span class="sy0">;</span>                        <span class="co1">// テンプレートはfrontendアプリケーション内に存在するので、パターンは見つからない</span></pre>

<p>解決策は、frontendキャッシュマネージャと同じ設定で、手動で<code>sfCache</code>オブジェクトを初期化することです。幸いにして、symfony内のすべてのキャッシュクラスはビューキャッシュマネージャの<code>remove</code>と同じサービスを供与する<code>removePattern</code>メソッドを提供します。</p>

<p>たとえば、<code>backend</code>アプリケーションが<code>id</code>が<code>12</code>であるユーザーに対して<code>frontend</code>アプリケーションのなかで<code>user/show</code>アクションのキャッシュをクリアしたい場合、つぎのコードを利用できます:</p>

<pre class="php"><span class="re0">$frontend_cache_dir</span> <span class="sy0">=</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_root_cache_dir'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="kw4">DIRECTORY_SEPARATOR</span><span class="sy0">.</span><span class="st_h">'frontend'</span><span class="sy0">.</span><span class="kw4">DIRECTORY_SEPARATOR</span><span class="sy0">.</span>SF_ENV<span class="sy0">.</span><span class="kw4">DIRECTORY_SEPARATOR</span><span class="sy0">.</span><span class="st_h">'template'</span><span class="sy0">;</span>
<span class="re0">$cache</span> <span class="sy0">=</span> <span class="kw2">new</span> sfFileCache<span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'cache_dir'</span> <span class="sy0">=&gt;</span> <span class="re0">$frontend_cache_dir</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//frontendのfactories.ymlで定義された設定と同じものを使う</span>
<span class="re0">$cache</span><span class="sy0">-&gt;</span><span class="me1">removePattern</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=12'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>異なるキャッシュ戦略に対して、キャッシュのオブジェクトの初期化を変更することだけが必要ですが、キャッシュの除去プロセスは変わりません:</p>

<pre class="php"><span class="re0">$cache</span> <span class="sy0">=</span> <span class="kw2">new</span> sfMemcacheCache<span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'prefix'</span> <span class="sy0">=&gt;</span> <span class="st_h">'frontend'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$cache</span><span class="sy0">-&gt;</span><span class="me1">removePattern</span><span class="br0">&#40;</span><span class="st_h">'user/show?id=12'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<a name="testing.and.monitoring.caching" id="testing.and.monitoring.caching"></a><h2>キャッシュのテストとモニタリング</h2>

<p>HTMLのキャッシュは、適切に処理されない場合、表示されるデータに矛盾が生じる可能性があります。要素に対してキャッシュを無効にするたびに、徹底的にテストし、調整するために実行ブーストのモニタリングを行います。</p>

<a name="building.a.staging.environment" id="building.a.staging.environment"></a><h3>ステージング環境を作成する</h3>

<p>開発環境ではHTMLのキャッシュはデフォルトで無効なので、運用環境のキャッシュシステムは開発環境で検出できない新しいエラーに陥りがちです。なんらかのアクションのためにHTMLのキャッシュを有効にする場合、このセクションではステージング(staging)と呼ばれる新しい環境を作ります。ステージング環境は<code>prod</code>環境と同じ設定(したがって、キャッシュが有効)ですが、<code>web_debug</code>設定は<code>on</code>です。</p>

<p>セットアップするには、アプリケーションの<code>settings.yml</code>ファイルを編集してリスト12-12の一番上に示されている行を追加します。</p>

<p>リスト12-12 - <code>frontend/config/settings.yml</code>のなかで、<code>staging</code>環境のための設定</p>

<pre><code>staging:
  .settings:
    web_debug:  on
    cache:      on
</code></pre>

<p>加えて、運用環境のフロントコントローラー(おそらく<code>myproject/web/index.php</code>)を新しい<code>frontend_staging.php</code>にコピーして新しいフロントコントローラーを作ります。つぎのように<code>getApplicationConfiguration()</code>メソッドに渡される引数を変更するためにこのファイルを編集します:</p>

<pre class="php"><span class="re0">$configuration</span> <span class="sy0">=</span> ProjectConfiguration<span class="sy0">::</span><span class="me2">getApplicationConfiguration</span><span class="br0">&#40;</span><span class="st_h">'frontend'</span><span class="sy0">,</span> <span class="st_h">'staging'</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>作業はこれだけです。新しい環境が手に入りました。ドメイン名の後にフロントコントローラー名を追加して使います:</p>

<pre><code>http://myapp.example.com/frontend_staging.php/user/list
</code></pre>

<a name="monitoring.performance" id="monitoring.performance"></a><h3>パフォーマンスをモニタリングする</h3>

<p>16章でWebデバッグツールバーとその内容について深く掘り下げて説明します。しかしながら、このツールバーはキャッシュの要素に関して有益な情報を提供します。キャッシュ機能の手短な説明はつぎのとおりです。</p>

<p>キャッシュ可能な要素(アクション、部分テンプレート、フラグメントなど)を含むページをブラウザーで閲覧するとき、図12-4で示されるようにWebデバッグツールバー(ウィンドウの右上のコーナー)が「ignore cache button」(緑で丸まった矢印)を表示します。このボタンはページをリロードして、キャッシュされた要素の処理を強制します。キャッシュはこのボタンでクリアされないことを覚えておいてください。</p>

<p>デバッグツールバーの右側の最後の数値はリクエストの実行期間です。ページ上でキャッシュを有効にした場合、この数値はページをロードする秒数を減らします。symfonyがスクリプトを再処理する代わりにキャッシュからデータを使うからです。このインディケータによって簡単にキャッシュの改善をモニタリングできます。</p>

<p>図12-4 - キャッシュを使うページのためのWebデバッグツールバー</p>

<p><img src="images/F1204.png" alt="キャッシュを使うページのためのWebデバッグツールバー" title="キャッシュを使うページのためのWebデバッグツールバー" /></p>

<p>デバッグツールバーはリクエストの処理の間に実行されたデータベースクエリの数も表示し、カテゴリごとの継続時間の詳細を示します(詳細を表示するtotal durationをクリックします)。このデータのモニタリングは、継続時間の合計と共に、キャッシュによってもたらされたすばらしいパフォーマンス改善の測定の助けになります。</p>

<a name="benchmarking" id="benchmarking"></a><h3>ベンチマーキングを行う</h3>

<p>多くの情報がWebデバッグツールバーで記録され利用可能になるので、デバッグモードはアプリケーションの速度を大きく減速させます。ですので、<code>staging</code>環境でブラウジングしているとき、表示される処理時間はデバッグモードが<code>off</code>になっている運用環境で何が起きたのかを表していません。</p>

<p>それぞれのリクエストの処理時間のより優れた概要を知るには、Apache BenchやJMeterなどのベンチマーキングツールを使うべきです。これらのツールによってロードテストが可能になり2つの重要な情報の断片が提供されます: 2つの情報とは特定のページの平均的な読み込み時間とサーバーの最大キャパシティです。平均的な読み込み時間のデータはキャッシュの有効によるパフォーマンスの改善をモニタリングするためにとても役立ちます。</p>

<a name="identifying.cache.parts" id="identifying.cache.parts"></a><h3>キャッシュの一部を識別する</h3>

<p>Webデバッグツールが有効にされたとき、図12-5で示されるように、キャッシュされた要素はそれぞれがトップ左側のキャッシュ情報のボックスを持つ赤いフレームによるページで識別されます。要素が実行された場合はボックスの背景が青色になり、ページがキャッシュから由来する場合は背景が黄色になります。キャッシュ情報をクリックするとキャッシュ要素の識別子、期限と最終修正以降の経過時間が表示されます。これは、文脈外の要素を処理するとき、要素が作られた時と実際にキャッシュできるテンプレートの部分を理解するために、問題を識別するための助けになります。</p>

<p>図12-5 - ページのキャッシュされた要素を識別する</p>

<p><img src="images/F1205.png" alt="ページのキャッシュされた要素を識別する" title="ページのキャッシュされた要素を識別する" /></p>

<a name="http.1.1.and.clientside.caching" id="http.1.1.and.clientside.caching"></a><h2>HTTP 1.1とクライアントサイドのキャッシュ</h2>

<p>HTTP 1.1プロトコルはブラウザーのキャッシュシステムをコントロールすることでアプリケーションを加速するために大いに役立つ一連のヘッダーを定義します。</p>

<p>World Wide Web Consortium(W3C, <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html</a>)のHTTP 1.1の仕様はこれらのヘッダーを詳細に説明をしています(訳注：<a href="http://www.studyinghttp.net/rfc_ja/rfc2616#Sec14">rfc2616の日本語訳</a>)。アクションがキャッシュを有効にしていて、<code>with_layout</code>オプションを使っている場合、アクションはつぎのセクションで説明される1つもしくは複数のメカニズムを利用します。</p>

<p>Webサイトのユーザーのブラウザーの一部がHTTP 1.1をサポートしていなかったとしても、HTTP 1.1のキャッシュ機能を使うことに関してリスクは存在しません。簡単に理解できないヘッダーを受けとるブラウザーはこれらの機能を無視するので、HTTP 1.1のキャッシュメカニズムをセットアップすることをお勧めします。</p>

<p>加えて、HTTP 1.1のヘッダーはプロキシサーバーとキャッシュサーバーも理解できます。ユーザーのブラウザーがHTTP 1.1を理解しない場合でも、それを利用するリクエストのroute内部でプロキシが存在できます。</p>

<a name="adding.an.etag.header.to.avoid.sending.unchanged.content" id="adding.an.etag.header.to.avoid.sending.unchanged.content"></a><h3>変更されていない内容の送信を回避するためにETagヘッダーを追加する</h3>

<p><code>ETag</code>機能が有効な場合、Webサーバーはレスポンス自身の署名を含む特別なヘッダーをレスポンスに追加します。</p>

<pre><code>ETag: "1A2Z3E4R5T6Y7U"
</code></pre>

<p>ユーザーのブラウザーはこの署名を保存し、同じページが必要になる次回にリクエストと一緒に再び送信します。新しい署名が最初のリクエスト以降にページが変更されていないことを示す場合、サーバーはレスポンスを返信しません。代わりに、<code>304: Not modified</code>ヘッダーに送信できます。CPUの時間(この例ではgzipが有効)とサーバーのための帯域(ページの転送)とクライアントのための時間(ページの転送)が節約されます。全体で、<code>ETag</code>ありのキャッシュ内のページは<code>ETag</code>なしのキャッシュ内のページよりもロードするのが速いです。</p>

<p>symfonyにおいて、アプリケーション全体に対して<code>settings.yml</code>のなかで<code>ETag</code>機能を有効にします。デフォルトの<code>ETag</code>設定はつぎのとおりです:</p>

<pre><code>all:
  .settings:
    etag: on
</code></pre>

<p>レイアウトありのキャッシュにおけるアクションは、<code>cache/</code>ディレクトリから直接レスポンスを取得するので処理がずっと高速になります。</p>

<a name="adding.a.lastmodified.header.to.avoid.sending.still.valid.content" id="adding.a.lastmodified.header.to.avoid.sending.still.valid.content"></a><h3>まだ有効な内容の送信を回避するためにLast-Modifiedヘッダーを追加する</h3>

<p>サーバーがレスポンスをブラウザーに送信するとき、ページに含まれるデータが最後に更新された時間を指定するために特別なヘッダーを追加できます:</p>

<pre><code>Last-Modified: Sat, 23 Nov 2006 13:27:31 GMT
</code></pre>

<p>ブラウザーはこのヘッダーを理解できるので、再びページをリクエストするとき、それに合わせて<code>If-Modified</code>ヘッダーを追加します:</p>

<pre><code>If-Modified-Since: Sat, 23 Nov 2006   13:27:31 GMT
</code></pre>

<p>サーバーはクライアントの値とアプリケーションによって返される値を比較できます。これらがマッチする場合、サーバーは<code>304: Not modified</code>ヘッダーを返し、<code>ETag</code>と同じように帯域とCPUの時間を節約します。</p>

<p>symfonyにおいて、別のヘッダーに対して行うことと同じように、<code>Last-Modified</code>応答ヘッダーを設定できます。たとえば、これをアクションのなかで利用できます:</p>

<pre class="php"><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">setHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'Last-Modified'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getDate</span><span class="br0">&#40;</span><span class="re0">$timestamp</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>この日付は、データベースもしくはファイルシステムから渡される、ページで使われるデータの実際の最終更新日になります。<code>sfResponse</code>オブジェクトの<code>getDate()</code>メソッドはタイムスタンプを<code>Last-Modified</code>ヘッダー(RFC1123)のために必要な書式の日付に変換します。</p>

<a name="adding.vary.headers.to.allow.several.cached.versions.of.a.page" id="adding.vary.headers.to.allow.several.cached.versions.of.a.page"></a><h3>キャッシュ済みのページを利用可能にするVaryヘッダーを追加する</h3>

<p>HTTP 1.1の別のヘッダーは<code>Vary</code>です。このヘッダーはページが依存するパラメーターがどれなのかを定義し、キャッシュのキーを作成するためにブラウザーとプロキシによって使われます。たとえば、ページの内容がCookieに依存する場合、<code>Vary</code>ヘッダーをつぎのように設定できます:</p>

<pre><code>Vary: Cookie
</code></pre>

<p>たいていの場合、アクション上でキャッシュを有効にすることは難しいです。なぜならページがCookie、ユーザーの言語、もしくはその他にしたがって変わるかもしれないからです。キャッシュのサイズを増やすことをいとわないのであれば、レスポンスの<code>Vary</code>ヘッダーを適切に設定してください。つぎのような<code>cache.yml</code>設定ファイルもしくはメソッドに関連する<code>sfResponse</code>を使うことで、この設定はアプリケーション全体のため、もしくはアクションをベースに行うことができます。:</p>

<pre class="php"><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addVaryHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'Cookie'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addVaryHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'User-Agent'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addVaryHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'Accept-Language'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>symfonyはこれらのパラメーターの値ごとに異なるバージョンのページをキャッシュに保存します。これはキャッシュのサイズを増やしますが、サーバーがこれらのヘッダーにマッチするリクエストを受けとるたびに、レスポンスは処理される代わりにキャッシュからとり込まれます。リクエストのヘッダーだけにしたがって変化するページのための偉大なパフォーマンスツールです。</p>

<a name="adding.a.cachecontrol.header.to.allow.clientside.caching" id="adding.a.cachecontrol.header.to.allow.clientside.caching"></a><h3>クライアントサイドのキャッシュを可能にするCache-Controlヘッダーを追加する</h3>

<p>これまで、ヘッダーを追加することによって、キャッシュ済みのページ保持する場合でも、ブラウザーはサーバーへのリクエストの送信を続けました。<code>Cache-Control</code>ヘッダーと<code>Expires</code>ヘッダーをレスポンスに追加することでこれを避けることができます。PHPにおいてこれらのヘッダーはデフォルトで無効ですが、サーバーへの不要なリクエストを避けるためにsymfonyはこれらのふるまいをオーバーライドできます。</p>

<p>通常は、<code>sfResponse</code>オブジェクトのメソッドを呼び出すことでこのふるまいを起動させます。アクションにおいて、ページがキャッシュされる最大時間(秒)を定義します:</p>

<pre class="php"><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addCacheControlHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'max_age=60'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>ページがキャッシュされる条件も指定できるので、プロバイダのキャッシュは(銀行口座の番号のように)秘密のデータのコピーを保存しません:</p>

<pre class="php"><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">addCacheControlHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'private=True'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>HTTPの<code>Cache-Control</code>ヘッダーを使うことで、サーバーとクライアントブラウザー間でのさまざまなキャッシュメカニズムを調整する機能が得られます。これらのディレクティブの詳細な概説については、W3Cの<code>Cache-Control</code>の仕様をご覧ください。</p>

<p>最後の1つの<code>Expires</code>ヘッダーはsymfonyを通して設定できます:</p>

<pre class="php"><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">setHttpHeader</span><span class="br0">&#40;</span><span class="st_h">'Expires'</span><span class="sy0">,</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getResponse</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getDate</span><span class="br0">&#40;</span><span class="re0">$timestamp</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<blockquote class="caution"><p>
  <code>Cache-Control</code>のメカニズムを有効にした場合、主な結果はサーバーのログがユーザーによって発せられたすべてのリクエストではなく、実際に受けとったリクエストのみを表示するようになることです。パフォーマンスがよくなれば、統計データではサイトの見た目の人気は減ることがあります。</p>
</blockquote>

<a name="summary" id="summary"></a><h2>まとめ</h2>

<p>選択したキャッシュタイプにしたがって、キャッシュシステムは可変のパフォーマンスの加速を提供します。ゲインが最大から最小のものから、キャッシュタイプはつぎのものがあります。</p>

<ul>
<li>スーパーキャッシュ</li>
<li>レイアウトありのアクションキャッシュ</li>
<li>レイアウトなしのアクションキャッシュ</li>
<li>テンプレート内のフラグメントキャッシュ</li>
</ul>

<p>加えて、部分テンプレートとコンポーネントも同様にキャッシュされます。</p>

<p>モデルもしくはセッション内のデータを変更することで一貫性のためにキャッシュを削除することが強制される場合、あなたはきめ細かい粒度で行うことができます。変更された要素のみが削除され、そのほかのものは保たれます。</p>

<p>あなたが間違った要素をキャッシュする場合、もしくは内在するデータを更新したときにキャッシュをクリアすることを忘れた場合、新しいバグが現れるかもしれないので、 キャッシュが有効にされたすべてのページを注意深くテストすることを忘れないでください。ステージング(staging)環境は、キャッシュのテスト専用で、そのために大いに役立ちます。</p>

<p>最後に、HTTP 1.1のプロトコルをsymfonyの高度なキャッシュ調整機能のなかで最大限活用してください。このことによってキャッシュタスクのなかでクライアントに影響を与えさらなるパフォーマンスのゲインを提供することになります。</p>
</div>
<div class="navigation">
<hr/>
<table width="100%">
<tr>
<td width="40%" align="left"><a href="11-Ajax-Integration.html">前の章</a></td>
<td width="20%" align="center"><a href="index.html">ホーム</a></td>
<td width="40%" align="right"><a href="13-I18n-and-L10n.html">次の章</a></td>
</tr>
</table>

</div>
</body>

</html>
